<template>
  <div class="map-utils">
    <div class="top">
      <div class="util-item" v-for="item in topUtils" :key="item.name">
        <div
          class="util-item__wrapper"
          :class="{
            active:
              activeUtilId === item.id ||
              (item.id === 'left-community-info' && leftPanelShow),
          }"
          @click="onUtilClick(item)"
        >
          <SvgIcon :icon-class="item.icon" :title="item.name" />
        </div>
      </div>

      <transition name="slide" mode="out-in">
        <DataCatalog
          class="map-util-component"
          v-show="activeUtilId === 'data-catalog'"
          ref="dataCatalogRef"
          :map-id="mapId"
          @close-detail="handleCloseDetail"
          @node-click="handleDataCatalogNodeClick"
          @node-check="handleNodeCheck"
        />
      </transition>

      <transition name="slide" mode="out-in">
        <LayerManagement
          class="map-util-component"
          v-show="activeUtilId === 'layers'"
          ref="layerManagementRef"
          :map-id="mapId"
        />
      </transition>

      <transition name="slide" mode="out-in">
        <ToolBox
          class="map-util-component"
          v-show="activeUtilId === 'toolbox'"
          ref="toolBoxRef"
          :map-id="mapId"
        />
      </transition>
    </div>

    <div class="bottom">
      <div class="util-item" v-for="item in bottomUtils" :key="item.name">
        <div
          class="util-item__wrapper"
          :class="{
            active: activeUtilId === item.id,
          }"
          @click="onUtilClick(item)"
        >
          <SvgIcon :icon-class="item.icon" :title="item.name" />
        </div>
      </div>

      <BaseMapSwitch
        :base-map-config="baseMapConfig"
        :base-map-list="baseMapList"
        @switch-base-map="switchBaseMap"
      />
    </div>
  </div>
</template>

<script setup>
import { ref } from 'vue'
import mapboxgl from 'mapbox-gl'
import { debounce } from 'lodash'
import { Message as ElMessage } from 'element-ui'
import SvgIcon from '@/components/svg-icon'
import BaseMapSwitch from './base-map/BaseMapSwitch.vue'
import DataCatalog from './data-catalog/DataCatalog.vue'
import LayerManagement from './layer-management/LayerManagement.vue'
import ToolBox from './tool-box/ToolBox.vue'

defineProps({
  mapId: {
    type: String,
    required: true,
  },
  baseMapConfig: {
    type: Object,
    required: true,
  },
  baseMapList: {
    type: Array,
    default: () => [],
  },
})

const emits = defineEmits([
  'get-current-location',
  'restore-to-home-location',
  'update:base-map-config',
  'show-left-fill-info',
  'show-catalog-detail',
  'node-check'
])

const dataCatalogRef = ref()
const layerManagementRef = ref()
const toolBoxRef = ref()

const topUtils = ref([
  {
    id: 'data-catalog',
    name: '数据目录',
    icon: 'data-catalog',
  },
  {
    id: 'layers',
    name: '图层管理',
    icon: 'layers',
  },
  {
    id: 'toolbox',
    name: '工具箱',
    icon: 'toolbox',
  },
  {
    id: 'current-location',
    name: '当前位置',
    icon: 'current-location',
  },
  {
    id: 'home-location',
    name: '初始位置',
    icon: 'home-location',
  },
  // {
  //   id: 'left-community-info',
  //   name: '填报信息',
  //   icon: 'fill-info',
  // },
])

const bottomUtils = ref([])

const activeUtilId = ref('data-catalog')
const leftPanelShow = ref(true)
const selectedCatalogNode = ref(null)

/**
 * 工具按钮点击事件
 *
 * @param {UtilItem} item 按钮
 */
const onUtilClick = (item) => {
  switch (item.id) {
    case 'data-catalog':
      toggleActiveUtil(item.id)
      break
    case 'layers':
      toggleActiveUtil(item.id)
      break
    case 'toolbox':
      toggleActiveUtil(item.id)
      break
    case 'current-location':
      getCurrentLocation()
      break
    case 'home-location':
      restoreToHomeLocation()
      break
    case 'left-community-info':
      openLeftPanel()
      break
    default:
      break
  }
}

/**
 * 切换工具按钮激活状态
 *
 * @param {string} id 工具按钮id
 */
const toggleActiveUtil = (id) => {
  if (activeUtilId.value === id) {
    activeUtilId.value = ''
  } else {
    activeUtilId.value = id
  }
}

/**
 * 获取当前定位
 */
const getCurrentLocation = debounce(() => {
  if ('geolocation' in navigator) {
    navigator.geolocation.getCurrentPosition(
      (position) => {
        emits(
          'get-current-location',
          new mapboxgl.LngLat(
            position.coords.longitude,
            position.coords.latitude
          )
        )
      },
      (error) => {
        console.error('定位失败:', error)
        let errorMessage
        switch (error.code) {
          case 1:
            errorMessage = '未授予定位权限'
            break
          case 2:
            errorMessage = '获取定位错误'
            break
          case 3:
            errorMessage = '获取定位超时'
            break
          default:
            errorMessage = '定位失败'
            break
        }
        ElMessage.error({
          message: errorMessage,
        })
      }
    )
  }
}, 300)

/**
 * 回到默认位置
 */
const restoreToHomeLocation = debounce(() => {
  emits('restore-to-home-location')
}, 300)

/**
 * 切换底图
 *
 * @param {BaseMapConfig} baseMapConfig 底图配置
 */
const switchBaseMap = (baseMapConfig) => {
  emits('update:base-map-config', baseMapConfig)
}

/**
 * 开启左侧统计面板
 *
 */
const openLeftPanel = () => {
  leftPanelShow.value = !leftPanelShow.value
  emits('show-left-fill-info')
}

/**
 * 关闭面板
 */
const closeUtilPanel = () => {
  activeUtilId.value = ''
}

/**
 * 根据父id查询数据目录选中的子id
 *
 * @param {string} parentId 父id
 *
 * @return {string[]} 选中的子id数组
 */
const getIncludeChildren = (parentId) => {
  return dataCatalogRef.value.getIncludeChildren(parentId)
}

const getItemCheckedStatus = (id) => {
  // return dataCatalogRef.value.getItemCheckedStatus(id)
}

/**
 * Handle data catalog node click
 *
 * @param {Object} nodeData - The clicked node data
 */
const handleDataCatalogNodeClick = (nodeData) => {
  selectedCatalogNode.value = nodeData
  emits('show-catalog-detail', nodeData)
}

const handleNodeCheck = (isChecked) => {
  emits('node-check', isChecked)
}

const handleCloseDetail = () => {
  emits('show-catalog-detail', null) // 传 null，通知父组件关闭详情
}

const setHighlightNode = (id) => {
  dataCatalogRef.value?.highlightNode(id)
}

defineExpose({
  closeUtilPanel: closeUtilPanel,
  getIncludeChildren: getIncludeChildren,
  getItemCheckedStatus: getItemCheckedStatus,
  openLeftPanel,
  leftPanelShow,
  selectedCatalogNode,
  setHighlightNode,
})
</script>

<style lang="scss" scoped>
.map-utils {
  $primary-color: #006fff;
  .util-item {
    position: relative;

    &:not(:first-of-type) {
      margin-top: 20px;
    }

    &__wrapper {
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: center;

      width: 40px;
      height: 40px;
      background: white;
      box-shadow: 0 0 6px 0 rgba(0, 10, 19, 0.2);
      border-radius: 18px;
      cursor: pointer;

      &:hover {
        .svg-icon {
          color: $primary-color;
        }
      }

      &.active {
        .svg-icon {
          color: $primary-color;
        }
      }

      .svg-icon {
        width: 20px;
        height: 20px;
        color: #27475f;
      }
    }
  }

  .map-util-component {
    position: absolute;
    right: calc(40px + 11px);
    background-color: white;
    box-shadow: 0 0 6px 0 rgba(0, 10, 19, 0.2);
    border-radius: 4px;
    overflow: hidden;
    z-index: 20;

    &.data-catalog {
      // 5px: component的top属性
      top: 5px;
      height: calc(100vh - 185px);
    }

    &.layer-management {
      height: 500px;
      top: calc(5px + (40px + 20px));
    }

    &.tool-box {
      top: calc(5px + (40px + 20px) * 2);
    }
  }

  .top {
    display: flex;
    flex-direction: column;

    align-items: flex-end;
    position: absolute;
    top: 18px;
    right: 22px;
  }

  .bottom {
    display: flex;
    flex-direction: column;

    align-items: flex-end;
    position: absolute;
    bottom: 10px;
    right: 22px;

    .base-map-switch {
      margin-top: 20px;
    }
  }
}

.slide-enter-active,
.slide-leave-active {
  transition: all 0.2s ease;
}

.slide-enter-from,
.slide-leave-to {
  transform: translateX(20%);
  opacity: 0.2;
}
</style>
